"""
baserequest
"""
import traceback

import requests

from urllib3.exceptions import InsecureRequestWarning

# 通过传入的bool值确定是否打印string
printfunc = lambda LogBool, string: print(string) if LogBool else print("")

# 关闭r对象
closeResult = lambda r: r.close() if 'r' in locals() and r else None
r = ''

USER_AGENTS = [
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.62 Safari/537.36",
    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; AcooBrowser; .NET CLR 1.1.4322; .NET CLR 2.0.50727)",
    "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Acoo Browser; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.0.04506)",
    "Mozilla/4.0 (compatible; MSIE 7.0; AOL 9.5; AOLBuild 4337.35; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)",
    "Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US)",
    "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 2.0.50727; Media Center PC 6.0)",
    "Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 1.0.3705; .NET CLR 1.1.4322)",
    "Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 5.2; .NET CLR 1.1.4322; .NET CLR 2.0.50727; InfoPath.2; .NET CLR 3.0.04506.30)",
    "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN) AppleWebKit/523.15 (KHTML, like Gecko, Safari/419.3) Arora/0.3 (Change: 287 c9dfb30)",
    "Mozilla/5.0 (X11; U; Linux; en-US) AppleWebKit/527+ (KHTML, like Gecko, Safari/419.3) Arora/0.6",
    "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.2pre) Gecko/20070215 K-Ninja/2.1.1",
    "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9) Gecko/20080705 Firefox/3.0 Kapiko/3.0",
    "Mozilla/5.0 (X11; Linux i686; U;) Gecko/20070322 Kazehakase/0.4.5",
    "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.8) Gecko Fedora/1.9.0.8-1.fc10 Kazehakase/0.5.6",
    "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11",
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/535.20 (KHTML, like Gecko) Chrome/19.0.1036.7 Safari/535.20",
    "Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; fr) Presto/2.9.168 Version/11.52",
]


def proxycount(*args, **kwargs):
    def outer_wrapper(func):
        def wrapper(*args, **kwargs):
            url = args[0]
            if "proxies" in kwargs.keys:
                proxies = kwargs["proxies"]
                pass
            result = func(*args, **kwargs)
            if not result[0]:
                pass
            return result

    pass


def BaseRequest(url, sn=None, LogBool=True, endstring="</html>", mark="", **kwargs):
    """
    网络请求的基本结构
    :param url:  请求的url
    :param sn:  会话  sn = requests.Session() 这样保存会话
    :param LogBool: 是否打印一些显示
    :param endstring:  判断html的结束字符串 一般html默认 </html> 结尾
    :param mark:  标志符 默认为""  你的结果中的一些字符串或特殊的标签都可以
    :param kwargs: requests请求的一些参数
    :return: true表示成功 false表示失败或需要进行检查的数据，同时返回r
    BoolResult, errString, r
    """
    r = None
    exMsg = None
    try:
        requests.urllib3.disable_warnings(InsecureRequestWarning)
        printfunc(LogBool, url)
        if sn:
            r = sn.get(url=url, **kwargs)
        else:
            r = requests.get(url=url, **kwargs)
    except:
        exMsg = '* ' + traceback.format_exc()
        printfunc(LogBool, exMsg)
    finally:
        closeResult(r)

    if exMsg:
        print("判断到except，请求出项错误")
        return False, "request", r

    if r.status_code != 200:
        print('error url:' + r.url)
        print('r.status_code:' + str(r.status_code))
        return False, "code", r

    if endstring:
        """
        请求有可能是html或者json等，如果有需要判断html结束的才启动这个选项
        """
        html = r.text.strip()
        if not html.endswith(endstring):
            print("not endswith {}".format(endstring))
            return False, "endString", r

    if mark:
        """
       验证请求是否成功  通过一个特征字符串或者html的标签来查找 保证下载的页面是我需要的页面
       而不是错误页面
       特征值有可能没有是网页出现问题  有可能是请求不完全 这个依照情况而定
        """
        html = r.text.strip()
        if html.find(mark) == -1:
            print('not found {}'.format(mark))
            return False, "Feature err", r
        else:
            print("found mark is {}".format(mark))

    return True, "", r


def BaseRequestPost(url, sn=None, data=None, LogBool=True, endstring="</html>", mark="", **kwargs):
    """
    网络请求的基本结构
    :param url:  请求的url
    :param sn:  会话  sn = requests.Session() 这样保存会话
    :param LogBool: 是否打印一些显示
    :param endstring:  判断html的结束字符串 一般html默认 </html> 结尾
    :param mark:  标志符 默认为""  你的结果中的一些字符串或特殊的标签都可以
    :param kwargs: requests请求的一些参数
    :return: true表示成功 false表示失败或需要进行检查的数据，同时返回r
    """
    r = None
    exMsg = None
    try:
        printfunc(LogBool, url)
        if sn:
            print("使用 sn请求")
            r = sn.post(url=url, data=data, **kwargs)
        else:
            print("使用 requets请求")
            requests.urllib3.disable_warnings(InsecureRequestWarning)
            r = requests.post(url=url, data=data, **kwargs)
    except:
        exMsg = '* ' + traceback.format_exc()
        printfunc(LogBool, exMsg)
    finally:
        closeResult(r)

    if exMsg:
        print("判断到except，请求出项错误")
        return False, "request", r

    if r.status_code != 200:
        print('error url:' + r.url)
        print('r.status_code:' + str(r.status_code))
        return False, "code", r

    if endstring:
        """
        请求有可能是html或者json等，如果有需要判断html结束的才启动这个选项
        """
        html = r.text.strip()
        if not html.endswith(endstring):
            print("not endswith {}".format(endstring))
            return False, "endString", r

    if mark:
        """
       验证请求是否成功  通过一个特征字符串或者html的标签来查找 保证下载的页面是我需要的页面
       而不是错误页面
       特征值有可能没有是网页出现问题  有可能是请求不完全 这个依照情况而定
        """
        html = r.text.strip()
        if html.find(mark) == -1:
            print('not found {}'.format(mark))
            return False, "Feature err", r

    return True, "", r


def MProxyRequest(pageUrl, retrynum=5, Feature=None, endstring="</html>", HEADERS=None, proxyRingList=None, timeout=60,
                  **kwargs):
    """
    通过代理请求的request get请求
    :param pageUrl:
    :param Feature:
    :param endstring:
    :param HEADERS:
    :param proxyRingList:
    :param timeout:
    :return:
    """
    BoolResult = False
    errString = ""
    r = None
    count = 0

    while count < retrynum:
        count += 1
        # 从列表中得到一个代理
        try:
            proxy = proxyRingList.pop()
        except:
            return False, "代理try错误", ""
        # 代理格式
        proxyss = {
            "http": "{}".format(proxy),
            "https": "{}".format(proxy)
        }
        print(proxyss)
        print("请求次数数: %s" % count)
        BoolResult, errString, r = BaseRequest(pageUrl,
                                               endstring=endstring,
                                               mark=Feature,
                                               headers=HEADERS,
                                               proxies=proxyss,
                                               timeout=timeout,
                                               **kwargs)
        if BoolResult:
            break
        else:
            if errString == "request":
                # 这里的try是为了兼容列表 而不是ringlist
                try:
                    proxyRingList.remove(proxy)
                except ValueError:
                    pass

    return BoolResult, errString, r


def MRequestSn(sn, pageUrl, retrynum=5, Feature=None, endstring="</html>", HEADERS=None, proxyRingList=None,
               timeout=60, **kwargs):
    """
    通过代理请求的sn get请求
    :param sn:
    :param pageUrl:
    :param Feature:
    :param endstring:
    :param HEADERS:
    :param proxyRingList:
    :param timeout:
    :return:
    """
    BoolResult = False
    errString = ""
    r = None
    count = 0
    while count < retrynum:
        count += 1
        print("请求次数数: %s" % count)
        # 从列表中得到一个代理
        try:
            proxy = proxyRingList.pop()
        except:
            return False, "代理try错误", ""
        # 代理格式
        proxyss = {
            'http': proxy,
            # 'http':'162.105.138.192:8092',
            'https': proxy  # key是指目标网站的协议
        }
        print(proxyss)
        BoolResult, errString, r = BaseRequest(pageUrl,
                                               sn=sn,
                                               endstring=endstring,
                                               mark=Feature,
                                               headers=HEADERS,
                                               proxies=proxyss,
                                               timeout=timeout, **kwargs)
        if BoolResult:
            break
        else:
            try:
                proxyRingList.remove(proxy)
            except ValueError:
                pass

    return BoolResult, errString, r


def MRequestSnPost(sn, pageUrl, data, retrynum=5, Feature=None, endstring="</html>", HEADERS=None, proxyRingList=None,
                   timeout=60):
    BoolResult = False
    errString = ""
    r = None
    count = 0
    while count < retrynum:
        count += 1
        # 从列表中得到一个代理
        try:
            proxy = proxyRingList.pop()
        except:
            return False, "代理try错误", ""
        # 代理格式
        proxyss = {
            'http': proxy,
            # 'http':'162.105.138.192:8092',
            'https': proxy  # key是指目标网站的协议
        }
        print(proxyss)
        BoolResult, errString, r = BaseRequestPost(pageUrl,
                                                   sn=sn,
                                                   data=data,
                                                   endstring=endstring,
                                                   mark=Feature,
                                                   headers=HEADERS,
                                                   proxies=proxyss,
                                                   timeout=timeout)
        if BoolResult:
            break
        else:
            try:
                proxyRingList.remove(proxy)
            except ValueError:
                pass

    return BoolResult, errString, r
